package com.ruoyi.charge.auth.service.impl;


import cn.hutool.core.lang.Validator;
import com.ruoyi.charge.auth.entity.ApiToken;
import com.ruoyi.charge.auth.service.LoginTokenService;
import com.ruoyi.charge.auth.utils.UUIDUtils;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;


@Slf4j
@Service
public class LoginTokenServiceImpl implements LoginTokenService {

    // AccessToken有效期限 单位秒
    public static final int ACCESSTOKEN_EXPIRE = 7200;
    // RefreshToken有效期限 单位小时
    private static final int REFRESHTOKEN_EXPIRE = 7;
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Autowired
    private RedisCache redisCache;

    /**
     * @param userId
     * @param refreshToken
     * @Title: refreshToken
     * @Description: 刷新token
     */
    @Override
    public ApiToken refreshToken(Long userId, String refreshToken, Integer type) {
        String cacheRefreshToken = (String) redisCache.getCacheObject(getRefreshTokenKeyByMemberId(userId));
        if (cacheRefreshToken == null) {
            throw new CustomException("REFRESH_TOKEN_INVALID refreshToken 失效，请重新登录！");
        }
        if (!refreshToken.equals(cacheRefreshToken)) {
            throw new CustomException("REFRESH_TOKEN_ERROR refreshToken 错误！");
        }
        ApiToken token = creatToken(userId, type);
        return token;
    }

    /**
     * @param userId
     * @Title: creatToken
     * @Description: 创建token
     */
    @Override
    public ApiToken creatToken(Long userId, Integer type) {
        ApiToken token = new ApiToken();
        token.setType(type);
        token.setUserId(userId);
        token.setAccessToken(UUIDUtils.uuid2());
        String refreshTokenKey = getRefreshTokenKeyByMemberId(userId);
        if (redisCache.existKey(refreshTokenKey)) {
            String cacheRefreshToken = (String) redisCache.getCacheObject(refreshTokenKey);
            token.setRefreshToken(cacheRefreshToken);
        } else {
            token.setRefreshToken(UUIDUtils.uuid2());
        }
        Date now = new Date();
        try {
            now = sdf.parse(sdf.format(now));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar oneHour = Calendar.getInstance();
        oneHour.setTime(now);
        oneHour.add(Calendar.SECOND, ACCESSTOKEN_EXPIRE);
        token.setAccessTokenExpireTime(oneHour.getTime());
        Calendar oneWeek = Calendar.getInstance();
        oneWeek.setTime(now);
        oneWeek.add(Calendar.DAY_OF_YEAR, REFRESHTOKEN_EXPIRE);
        token.setRefreshTokenExpireTime(oneWeek.getTime());
        token.setUpdateTime(now);
        //缓存token信息
        redisCache.setCacheObject(getTokenKey(token.getAccessToken()), token, ACCESSTOKEN_EXPIRE, TimeUnit.SECONDS);
//        redisCache.setCacheObject(getTokenKey(token.getAccessToken()), token, 1800, TimeUnit.SECONDS);

        //设置refreshToken
        redisCache.setCacheObject(getRefreshTokenKeyByMemberId(userId), token.getRefreshToken(), 1, TimeUnit.DAYS);
//        redisCache.setCacheObject(getRefreshTokenKeyByMemberId(userId), token.getRefreshToken(), REFRESHTOKEN_EXPIRE, TimeUnit.DAYS);
//        redisCache.setCacheObject(getRefreshTokenKeyByMemberId(userId), token.getRefreshToken(), 3600, TimeUnit.SECONDS);

        //设置会员ID redis key=accessToken:xxxx
        redisCache.setCacheObject(getAccessTokenKeyByMemberId(userId), token.getAccessToken(), ACCESSTOKEN_EXPIRE, TimeUnit.SECONDS);
//        redisCache.setCacheObject(getAccessTokenKeyByMemberId(userId), token.getAccessToken(), 180, TimeUnit.SECONDS);

        return token;
    }

    /**
     * 根据会员ID获取AccessToken的key
     */
    @Override
    public String getAccessTokenKeyByMemberId(Long userId) {
        return "accessToken_userId:" + userId;
    }

    /***
     * 根据会员ID获取RefreshToken的key
     */
    @Override
    public String getRefreshTokenKeyByMemberId(Long userId) {
        return "refreshToken_userId:" + userId;
    }

    /**
     * 根据token获取AccessToken的key
     */
    @Override
    public String getTokenKey(String token) {
        return "accessToken:" + token;
    }

    @Override
    public ApiToken getTokenByAccessToken(String accessToken) {

        String tokenKey = getTokenKey(accessToken);
        if (redisCache.existKey(tokenKey)) {
            ApiToken apiToken = redisCache.getCacheObject(tokenKey);
            return apiToken;
        }
        return null;
    }


    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    @Override
    public Long getLoginUserId(HttpServletRequest request) {
        // 获取请求携带的令牌
        String token = request.getHeader("token");
        if (Validator.isNotEmpty(token)) {
            String apiTokenKey = getTokenKey(token);
            if (redisCache.existKey(apiTokenKey)) {
                ApiToken apiToken = redisCache.getCacheObject(apiTokenKey);
                return apiToken.getUserId();
            }
        }
        return null;
    }

    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    @Override
    public ApiToken getLoginInfo(HttpServletRequest request) {
        // 获取请求携带的令牌
        String token = request.getHeader("token");
        if (Validator.isNotEmpty(token)) {
            String apiTokenKey = getTokenKey(token);
            if (redisCache.existKey(apiTokenKey)) {
                ApiToken apiToken = redisCache.getCacheObject(apiTokenKey);
                return apiToken;
            }
        }
        return null;
    }

}